package com.nulldev.util.crypto.encryptAPI.manage;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import com.nulldev.util.crypto.encryptAPI.AES;
import com.nulldev.util.crypto.encryptAPI.DES;
import com.nulldev.util.crypto.encryptAPI.DualXOR;
import com.nulldev.util.crypto.encryptAPI.Huffman;
import com.nulldev.util.crypto.encryptAPI.LiteString;
import com.nulldev.util.crypto.encryptAPI.XOR;
import com.nulldev.util.crypto.encryptAPI.XOROneTime;
import com.nulldev.util.crypto.encryptAPI.XXTEA;
import com.nulldev.util.crypto.encryptAPI.experimental.Shifter;
import com.nulldev.util.java.JVMUtil;
import com.nulldev.util.java.ReflectionUtils;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.other.ArrayUtils;

public class EncryptAPI {

	private static final Logger log = LoggerFactory.getLogger(true, true);
	public static final DefaultEncryptor DEFAULT_ENCRYPTOR = new DefaultEncryptor();
	private static final LinkedList<Encryptor> enc = new LinkedList<Encryptor>();
	static {
		if (enc.isEmpty()) {
			enc.add(DEFAULT_ENCRYPTOR);
			enc.add(new DES());
			enc.add(new XOROneTime());
			enc.add(new XXTEA());
			enc.add(new AES());
			enc.add(new XOR());
			enc.add(new Huffman());
			enc.add(new LiteString());
			enc.add(new DualXOR());
			enc.add(new Shifter());
		}
	}
	
	public static boolean register(final Encryptor encryptor) {
		return enc.add(encryptor);
	}
	
	public static Encryptor getEncryptorByID(final String id) {
		if (id == null) {
			return DEFAULT_ENCRYPTOR;
		}
		for (final Encryptor e : (LinkedList<Encryptor>) enc.clone()) {
			if (e.getEncryptorID().equals(id)) {
				return e;
			}
		}
		return DEFAULT_ENCRYPTOR;
	}
	
	public static Encryptor getEncryptorForEncryption(final String id) {
		if (id == null) {
			return DEFAULT_ENCRYPTOR;
		}
		for (final Encryptor e : (LinkedList<Encryptor>) enc.clone()) {
			if (ArrayUtils.contains(e.supportedEncryptors(), id)) {
				return e;
			}
		}
		return DEFAULT_ENCRYPTOR;
	}
	
	public static boolean isEncryptorByID(final String id) {
		final Encryptor enc = getEncryptorByID(id);
		return !isDefault(enc);
	}
	
	public static boolean isEncryptorByEncryption(final String id) {
		final Encryptor enc = getEncryptorForEncryption(id);
		return !isDefault(enc);
	}

	public static boolean isDefault(final Encryptor encryptor) {
		return encryptor == DEFAULT_ENCRYPTOR;
	}

	public static String[] getEncryptors() {
		final ArrayList<String> enc = new ArrayList<String>();
		for (final Encryptor en : (LinkedList<Encryptor>) EncryptAPI.enc.clone()) {
			enc.add(en.getEncryptorID());
		}
		return ArrayUtils.arrayListToArray(enc);
	}

	public static List<Encryptor> getEncryptorsList() {
		return (LinkedList<Encryptor>) enc.clone();
	}
}
